/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-12
 * V4.0
 */
package com.jphenix.servlet.service;

import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.servlet.interfaceclass.IAppSession;
import com.jphenix.share.util.BaseUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.docs.Running;
import com.jphenix.standard.serialno.ISN;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 应用层会话处理服务
 * @author 刘虻
 * 2013-1-8 上午10:36:36
 */
@ClassInfo({"2014-06-12 19:12","应用层会话处理服务"})
@Running({"1","init"})
public class AppSessionService extends ABase implements IAppSession {
	
	protected ISN sn = null; //序列号生成类
	
	 //全局会话信息容器
	protected HashMap<String,SessionVO> sessionMap = new HashMap<String,SessionVO>();
	protected CheckThread checkThread = null; //检测线程
	protected boolean checking = false; //是否正在检测
	
	/**
	 * 检测会话超时线程
	 * @author 刘虻
	 * 2013-1-8 上午10:43:46
	 */
	protected class CheckThread extends Thread {
		
		/**
		 * 构造函数
		 * @author 刘虻
		 */
		public CheckThread() {
			super("AppSessionService-CheckThread");
		}
		
		/**
		 * 覆盖方法
		 * 刘虻
		 * 2013-1-8 上午10:50:34
		 */
		@Override
        public void run() {
			try {
				while(true) {
					//延时间隔检测
					Thread.sleep(10000);
					
					checkTimeOut(); //检测会话信息超时
				}
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 会话信息容器
	 * @author 刘虻
	 * 2013-1-8 上午10:40:10
	 */
	protected class SessionVO {
		public long outTime; //超时单位时间
		public long timeOut; //超时时间
		public String key; //会话主键
		public HashMap<String,SessionVO> sessionMap = new HashMap<String,SessionVO>();
	}
	
	/**
	 * 构造函数
	 * @author 刘虻
	 */
	public AppSessionService() {
		super();
	}

	/**
	 * 初始化
	 * 刘虻
	 * 2013-1-8 上午10:52:29
	 * @throws Exception 异常
	 */
	public void init() throws Exception {
		//构建序列号生成类
		sn = getBean(ISN.class);
		//构建检测线程
		checkThread = new CheckThread();
		checkThread.start();
	}
	
	
	/**
	 * 检测会话信息超时
	 * 刘虻
	 * 2013-1-8 上午11:53:53
	 */
	protected void checkTimeOut() {
		if(checking) {
			return;
		}
		checking = true;
		//获取所有会话主键
		List<String> keyList = BaseUtil.getMapKeyList(sessionMap);
		for(Object key:keyList) {
			//会话信息
			SessionVO sVO = sessionMap.get(key);
			if(sVO==null) {
				continue;
			}
			if(sVO.timeOut>0 && sVO.timeOut<System.currentTimeMillis()) {
				//超时移除
				sessionMap.remove(key);
			}
		}
		checking = false;
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2013-1-8 上午10:36:36
	 */
	@Override
    public String createSession(long outTime) {
		String key = sn.getSID(); //构建新的序列号
		//构建新的会话容器
		SessionVO sVO = new SessionVO();
		sVO.key = key;
		sVO.outTime = outTime;
		if(outTime>0) {
			sVO.timeOut = System.currentTimeMillis()+outTime;
		}
		sessionMap.put(key,sVO);
		return key;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2013-1-8 上午10:36:36
	 */
	@Override
    public boolean checkSession(String key) {
		//获取指定会话信息
		SessionVO sVO = sessionMap.get(key);
		if(sVO==null) {
			return false;
		}
		//刷新超时时间
		if(sVO.outTime>0) {
			sVO.timeOut = System.currentTimeMillis()+sVO.outTime;
		}
		return true;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2013-1-8 上午10:56:20
	 */
	@Override
    public Map<String,SessionVO> getSessionMap(String key) {
		//获取对应的会话信息类
		SessionVO sVO = sessionMap.get(key);
		if(sVO!=null) {
			//刷新超时时间
			if(sVO.outTime>0) {
				sVO.timeOut = System.currentTimeMillis()+sVO.outTime;
			}
			return sVO.sessionMap;
		}
		return null;
	}

	/**
	 * 注销会话信息
	 * 刘虻
	 * 2013-1-8 下午1:52:40
	 * @param key 会话主键
	 */
	@Override
    public void destorySession(String key) {
		//移出指定会话信息
		sessionMap.remove(key);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2013-1-8 下午3:28:42
	 */
	@Override
    public Object getAttribute(String sessionKey, String key) {
		//获取会话信息容器
		Map<String,SessionVO> sessionMap = getSessionMap(sessionKey);
		if(sessionMap==null) {
			return null;
		}
		return sessionMap.get(key);
	}
}
